// **********************************************************************
//                            Project Nitro
//                        ---------------------
//
//  File        : WorldDisplay.cpp
//  Description : Display world (level, cars, ...)
//  Author      : Guillaume Delhumeau <guillaume.delhumeau@gmail.com>
//  License     : GNU General Public License 3
//
// **********************************************************************

#include "WorldDisplay.h"
#include "Screen.h"
#include "Car.h"
#include "Level.h"

/************************************************************************/
/* Constants                                                            */
/************************************************************************/
static const float SCROLLING_LIMIT = 0.4f;

/************************************************************************/
/* Constructor                                                          */
/************************************************************************/
WorldDisplay::WorldDisplay(Screen & screen):
_screen(screen)
{
	_scroll_x = 0;
	_scroll_y = 0;
	_screen_width = 0;
	_screen_height = 0;
}

/************************************************************************/
/* Draw                                                                 */
/************************************************************************/
void WorldDisplay::draw()
{
	_compute_scrolling();

	real car_on_screen_x = _p_main_car->get_matrix().GetX() - _scroll_x;
	real car_on_screen_y = - _p_main_car->get_matrix().GetZ() - _scroll_y;

	_screen.clear();
	_p_level->draw(_screen, _scroll_x, _scroll_y);
	_p_main_car->draw(_screen, car_on_screen_x, car_on_screen_y);
	_screen.display();
}

/************************************************************************/
/* Compute scrolling                                                    */
/************************************************************************/
void WorldDisplay::_compute_scrolling()
{
	_compute_scrollong_if_screen_resized();

	// Scrolling on X axis
	_compute_scrolling_axis(_screen.get_gc().get_width(), _scroll_x,
		_p_main_car->get_matrix().GetX() - _scroll_x, _p_level->get_map_width());

	// Scrolling on Y axis (Z for car)
	_compute_scrolling_axis(_screen.get_gc().get_height(), _scroll_y,
		-_p_main_car->get_matrix().GetZ() - _scroll_y, _p_level->get_map_height());
}

/************************************************************************/
/* If the screen has been resized, we have to update scrolling          */
/************************************************************************/
void WorldDisplay::_compute_scrollong_if_screen_resized()
{
	int width = _screen.get_gc().get_width();
	int height = _screen.get_gc().get_height();	

	if(width != _screen_width)
	{
		int dx = width - _screen_width;
		_scroll_x += dx / 2;
		_screen_width = width;
	}
	if(height != _screen_height)
	{
		int dy = height - _screen_height;
		_scroll_y += dy / 2;
		_screen_height = height;
	}
}

/************************************************************************/
/* Compute scrolling on a the desired axis                              */
/************************************************************************/
void WorldDisplay::_compute_scrolling_axis(int screen_size,
										   real & scroll_axis,
										   real car_pos_on_screen,
										   int map_size)
{
	
	if(car_pos_on_screen < screen_size * SCROLLING_LIMIT)
	{
		real d = car_pos_on_screen - screen_size * SCROLLING_LIMIT;
		scroll_axis += d;
	}
	else if(car_pos_on_screen > screen_size * (1.0f - SCROLLING_LIMIT))
	{
		real d = car_pos_on_screen - screen_size * (1.0f - SCROLLING_LIMIT);
		scroll_axis += d;
	}	

	if(scroll_axis < 0)
	{
		scroll_axis = 0;
	}
	else if(scroll_axis + screen_size >=	map_size)
	{
		scroll_axis = (real)map_size - screen_size;
	}
	
}